package com.alibaba.citrus.cr.mn.order.center.facade.function.asynctask;

import com.alibaba.citrus.cr.mn.order.center.common.util.StopWatchUtils;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.lattice2.epoch.db.service.CustomSequenceAccessor;
import com.alibaba.lattice2.epoch.middleware.mq.runtime.EpochMessageService;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectResult;
import com.epoch.app.bcorder.contants.BcOrderConstants;
import com.epoch.app.crb2btradecenter.messagetask.model.MessageTask;
import com.epoch.app.crb2btradecenter.messagetask.service.MessageTaskService;
import com.epoch.app.crb2btradecenter.model.dto.MessageTaskLoadListRequest;
import com.epoch.app.crb2btradecenter.model.enums.MessageTaskTypeEnum;
import com.google.common.collect.Maps;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author zhangxiaorui
 * @ClassName AsyncTaskCreateService
 * @description: TODO
 * @date 2023/05/17 16:51
 * @version: 1.0
 */
@Service
public class AsyncTaskCreateService {
    private static final Log log = Log.getLogger(AsyncTaskCreateService.class);
    private static final String ASYNC_TASK_CREATE_MQ_CODE = "order_async_task_create_listener";
    private static final String ASYNC_TASK_CREATE_MQ_TOPIC = "CR_SALEORDER_V2";
    private static final String ASYNC_TASK_CREATE_MQ_TAG = "ORDER_TASK_CREATE";
    private static final String ASYNC_TASK_PARAM_FILE  = "request.log";
    private static final String ASYNC_TASK_RESULT_FILE = "result.log";
    private static final String ASYNC_TASK_FILE_PATH = "orderCenter/asyncTask/%s/";

    @Resource
    private CustomSequenceAccessor customSequenceAccessor;
    @Autowired
    private EpochMessageService messageService;
    @Resource
    private MessageTaskService messageTaskService;
    @Resource
    private AsyncTaskOssService asyncTaskOssService;

    public String createAsyncTask(String reqNo, String fromSys, String requestParams, MessageTaskTypeEnum messageTaskTypeEnum) {
        // 校验幂等处理，防止多次创建任务
        StopWatchUtils.start("订单中心一盘货销售订单", "idempotentProcess");
        String messageBatchNo = idempotentProcess(reqNo, fromSys);
        StopWatchUtils.stop();
        if (StringUtils.isNotBlank(messageBatchNo)) {
            return messageBatchNo;
        }

        StopWatchUtils.start("订单中心一盘货销售订单", "getNextStringSequence");
        String innerSequenceNo = customSequenceAccessor.getNextStringSequence("cr_b2b_trade_center", "batchCreateOrderSequence");
        StopWatchUtils.stop();

        // 1.0 OSS文件上传
        StopWatchUtils.start("订单中心一盘货销售订单", "uploadRequestOss");
        String ossFileUrl = uploadRequestOss(requestParams, innerSequenceNo);
        StopWatchUtils.stop();

        // 2.0 任务创建
        StopWatchUtils.start("订单中心一盘货销售订单", "createMessageTask");
        String taskId = createMessageTask(reqNo, fromSys, innerSequenceNo, ossFileUrl, messageTaskTypeEnum);
        StopWatchUtils.stop();

        // 3.0 消息发送
        StopWatchUtils.start("订单中心一盘货销售订单", "sendMessage");
        sendMessage(taskId, innerSequenceNo);
        StopWatchUtils.stop();
        return innerSequenceNo;
    }

    private String idempotentProcess(String reqNo, String fromSys) {
        try {
            MessageTaskLoadListRequest loadRequest = new MessageTaskLoadListRequest();
            loadRequest.setReqNo(reqNo);
            loadRequest.setFromSys(fromSys);
            Result<List<MessageTask>> result = messageTaskService.loadList(loadRequest);
            if(Objects.isNull(result) || CollectionUtils.isEmpty(result.getResult())) {
                return null;
            }
            return result.getResult().get(0).getBatchNo();
        } catch (Exception e) {
            log.error("AsyncTaskCreateService#idempotentProcess error", e);
            return null;
        }
    }

    public void appendAsyncTaskHandleResult(String resultData, String sequenceNo, MessageTask messageTask) {

        PutObjectResult oss = asyncTaskOssService.getOssClient(BcOrderConstants.OSS_NAME())
                .setBucketName(BcOrderConstants.OSS_BUCKET())
                .setFileName(ASYNC_TASK_RESULT_FILE)
                .setFilePath(String.format(ASYNC_TASK_FILE_PATH, sequenceNo))
                .setObjectMetadata(new ObjectMetadata())
                .upload(new ByteArrayInputStream(resultData.getBytes(StandardCharsets.UTF_8)));

        log.info("异步任务上传oss返回结果:{}", JSONObject.toJSONString(oss));

        // 返回绝对路径 结果路径
        String filePath = String.format(ASYNC_TASK_FILE_PATH, sequenceNo) + ASYNC_TASK_RESULT_FILE;
        messageTask.setResultMessage(filePath);
        messageTaskService.update(messageTask);
    }

    public String downloadOfTaskParams(String absolutePath) {
        log.info("AsyncTaskCreateService_download_Start absolutePath={}",absolutePath);
        String ossContent = asyncTaskOssService.getOssClient(BcOrderConstants.OSS_NAME())
                .setBucketName(BcOrderConstants.OSS_BUCKET())
                .setObjectMetadata(new ObjectMetadata())
                .download(absolutePath);
        log.info("AsyncTaskCreateService_download_Result ossContent={}", ossContent);
        return ossContent;
    }

    private void sendMessage(String taskId, String sequenceNo) {

        Boolean batchSendResp = messageService.sendMessage(ASYNC_TASK_CREATE_MQ_CODE, ASYNC_TASK_CREATE_MQ_TOPIC,
                ASYNC_TASK_CREATE_MQ_TAG,
                sequenceNo, sequenceNo, getMQProperties());

        log.info("OrderCenterCreate_MQ_Result,taskID={}, sequenceNo={}, Resp={}",
                taskId, sequenceNo, batchSendResp);
    }

    private String createMessageTask(String reqNo, String fromSys, String innerSequenceNo, String ossFileUrl, MessageTaskTypeEnum messageTaskTypeEnum) {
        MessageTask messageTask = new MessageTask();
        messageTask.setReqNo(reqNo);
        messageTask.setFromSys(fromSys);
        messageTask.setBatchNo(innerSequenceNo);
        messageTask.setType(messageTaskTypeEnum.getValue());
        messageTask.setResultContent(ossFileUrl);
        messageTask.setGmt_create(new Date());
        messageTask.setGmt_modified(new Date());
        messageTask.setStatus(1);
        messageTask.setVersion(1);
        log.info("OrderCenterCreate_Async_Task MessageTask={}", JSONObject.toJSONString(messageTask));
        return messageTaskService.create(messageTask).getId();
    }

    private String uploadRequestOss(String requestParams, String sequenceNo) {
        String filePath = String.format(ASYNC_TASK_FILE_PATH, sequenceNo);

        PutObjectResult oss = asyncTaskOssService.getOssClient(BcOrderConstants.OSS_NAME())
                .setBucketName(BcOrderConstants.OSS_BUCKET())
                .setFileName(ASYNC_TASK_PARAM_FILE)
                .setFilePath(filePath)
                .setObjectMetadata(new ObjectMetadata())
                .upload(new ByteArrayInputStream(requestParams.getBytes(StandardCharsets.UTF_8)));

        log.info("异步任务上传oss返回结果:{}", JSONObject.toJSONString(oss));
        // 返回绝对路径
        return filePath + ASYNC_TASK_PARAM_FILE;
    }

    private static Map<String, String> getMQProperties() {
        Map<String, String> map = Maps.newHashMap();
        map.put("_CZ_KEY", BcOrderConstants.TENANT_ID());
        log.info("getMQProperties map={}", JSONObject.toJSONString(map));
        return map;
    }
}
